有時坐擁許多工具,但卻不知如何應用。
PHP 在 5.4.0 之後就內建 Built-in Web Server,這個功能可以在不用安裝 Apache 或 Nginx 的情況下就能順利啟動開發時期專用的網頁伺服器。
在翻閱某些坊間的 PHP 書籍時,還是時常看到花費一到兩個小節的篇幅去安裝 Apache 或 Nginx(或是用 WAMP、WNMP 之類的整合環境),這純粹是浪費時間。
PHP 的繁體中文且非翻譯書基本上都是垃圾
在安裝 PHP 之後,我們可以利用一個指令啟動 Built-in Web Server
php -S localhost:8000
上述指令會監聽目前所在的資料夾,並且啟動一個可以執行 PHP 的環境。假設存在一個檔案 a.php
,便可以透過 curl “localhost:8000/a.php”
去執行該 PHP Script 並且察看結果。
關於前端控制器模式,建議可以參見我前年在 iThome 鐵人賽的發文:設計模式 - 前端控制器模式(Front Controller Pattern)
對於這類「專案根目錄」與「網站入口點」不同的情況,可以利用 -t
參數額外指定運行資料夾
php -S localhost:8000 -t public/
以上假設網站入口點位於 public/
資料夾下。
只要修改 localhost:8000
中的 8000
,即可在不同的 Port 上啟動 Server。這在 Port 佔用或具有多個專案時相當好用。
對於 localhost:8000
中的 localhost
解釋起來較為麻煩,這篇花一點篇幅做解釋:
localhost
,只有自己本機才能夠存取,通常這已經足夠使用0.0.0.0
表示監聽所有來源
使用前端控制器模式後,我們的應用程式可能有些規則:
此時,我們會需要撰寫一個 server.php
的設定檔:(這份檔案來自 Laravel 的 server.php,這也是 Laravel 在啟動內置伺服器時的設定檔)
// server.php
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
if ($uri !== '/' && file_exists(__DIR__."/public$uri")) {
// return false 表示請內置伺服器直接存取該檔案,不經過特別處理
return false;
}
// 其餘的內容交給應用程式的入口點(/public/index.php)處理
require_once __DIR__.'/public/index.php';
之後,使用 php -S localhost:8000 -t public/ server.php
即可依照這個設定檔啟動內置伺服器。
可以利用 PHP_SAPI
這個 const 去取得目前 PHP 運行環境所使用的 API 類型。
if (PHP_SAPI === 'cli-server') {
// 表示目前使用的是 PHP 內置伺服器
}
註:PHP_SAPI
跟 php_sapi_name()
將會有相同的內容,通常建議用 PHP_SAPI
即可
註:除了 cli
或 cli-server
之外,很難利用 PHP_SAPI
去判斷目前的 Web Server 與使用環境,例如 Apache 就有 apache
, apache2filter
及 apache2handler
等不同的可能值
根據 PHP 官方建議
PHP 內置伺服器僅適用於開發時期(這非常重要)
其理由在於 PHP 內置伺服器是屬於單執行緒,而且長久執行可能存在 Memory Leak 的問題,所以不可用於產品環境。
如果希望像 Node.js 或 Golang 那樣,可以直接啟動一個 Web Server 並且提供正式服務,可以考慮使用 swoole 或 roadrunner,關於這兩個內容我應該會再用其它文章做說明。
在前言的部份,我提到了「PHP 的繁體中文且非翻譯書基本上都是垃圾」,雖然加上了刪除線,不過其實並非開玩笑。
拿個自身經驗來說,在 2012 年初學 PHP 時曾經購買了陳惠貞及陳俊榮當年度撰寫的書籍,直到 2016 年下旬該書雖然不再出版,但僅僅只是改了個名字在內容幾乎沒有變動的情況下再次出版。
先不提 2012 年用根本沒有推出的 PHP 6 作為噱頭的詐騙書名,2016 年的書籍中宣稱自己是 PHP 7 卻仍是把 2012 年的範例程式拿來複製貼上,而且在我的印象中還完全沒有提到 PDO。
很顯然地,並不是只有這個作者、這系列書有這樣的行為。
在數次到實體書店翻閱之後,我認為這算是出版業界一個相當病態的騙錢手段:不在乎出版品質,只在乎能否用聳動的書名、很新潮的技術名詞推銷很快就會過時的垃圾內容。